package com.zhupanlin.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.SessionRepository;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

/**
 * 描述信息：
 *
 * @author zhupanlin
 * @version 1.0
 * @date 2024/12/20 14:33
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final FindByIndexNameSessionRepository findByIndexNameSessionRepository;

    @Autowired
    public SecurityConfig(FindByIndexNameSessionRepository findByIndexNameSessionRepository) {
        this.findByIndexNameSessionRepository = findByIndexNameSessionRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .logout()
                .and()
                .csrf().disable()
                .sessionManagement() // 开启会话管理
                .maximumSessions(1) // 允许会话最大并发只能一个客户端 后面登录的会把前面的挤下去
//                .expiredUrl("/login") // 传统 web 页面，用户被挤下线后的跳转路径
                .expiredSessionStrategy(event -> { // 前后端分离处理方案
                    HttpServletRequest request = event.getRequest();
                    HttpServletResponse response = event.getResponse();
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("status", 500);
                    map.put("msg", "当前会话已经失效，请重新登录!");
                    String json = new ObjectMapper().writeValueAsString(map);
                    response.setContentType("application/json;charset=utf-8");
                    response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
                    response.getWriter().write(json);
                    response.flushBuffer();
                })
                .maxSessionsPreventsLogin(true) // 一旦登录后，后续用户禁止登录，只有当前用户退出注销后，才可以再次登录
                .sessionRegistry(sessionRegistry()) // 将 session 将给谁管理
        ;
    }

    /**
     * 创建 session 同步到 redis 的方案
     * @return
     */
    @Bean
    public SpringSessionBackedSessionRegistry sessionRegistry() {
        return new SpringSessionBackedSessionRegistry(findByIndexNameSessionRepository);
    }


    /*@Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }*/
}
